using System.Reflection;
using AutoMapper;
using AutoMapper.Configuration;
using ZeroSum.Extend.Mapper.Annotations;
using ZeroSum.Extend.Mapper.Extensions;
using ZeroSum.Extensions;
using ZeroSum.Helpers;

namespace ZeroSum.Extend.Mapper;

/// <summary>
///     自动扫描所有实现了ITypeConverter的类并创建Map
/// </summary>
public class AutoRegisterProfile : Profile
{
    public AutoRegisterProfile()
    {
        var assemblies = AssemblyHelper.GetProjectAssemblies().ToArray();

        AddConverterMaps(assemblies);
        AddMapToMaps(assemblies);
    }

    /// <summary>
    ///     创建所有基于 ITypeConverter<,> 的映射
    /// </summary>
    /// <param name="assemblies"></param>
    private void AddConverterMaps(Assembly[] assemblies)
    {
        var converterTypes = assemblies.GetConverterTypes();
        foreach (var type in converterTypes)
            CreateMap(type.SourceType, type.DestinationType).ConvertUsing(type.Converter);
    }

    /// <summary>
    ///     创建所有基于 MapTo 的映射
    /// </summary>
    /// <param name="assemblies"></param>
    private void AddMapToMaps(Assembly[] assemblies)
    {
        var types = assemblies.GetMapToTypes();
        foreach (var type in types)
        {
            var maps = type.GetAttributes<AutoMapToAttribute>();
            foreach (var map in maps) AddMapToMap(type, map);
        }
    }

    /// <summary>
    ///     基于 MapTo 创建单个映射
    /// </summary>
    /// <param name="type"></param>
    /// <param name="map"></param>
    private void AddMapToMap(Type type, AutoMapToAttribute map)
    {
        var expression = CreateMap(type, map.TargetType);

        // 处理所有属性上的注解
        var configurableMembers = type.GetMembers(BindingFlags.Public | BindingFlags.Instance);
        foreach (var memberInfo in configurableMembers)
        foreach (var provider in memberInfo.GetCustomAttributes().OfType<IMemberConfigurationProvider>())
            expression.ForMember(memberInfo.Name, cfg => provider.ApplyConfiguration(cfg));

        // 处理 MapTo本身的委托
        map.ApplyConfiguration(expression);
    }
}